package rpcserver

import (
	"context"
	"fmt"
	"gitee.com/851537/gbase"
	rpcbase "gitee.com/851537/gpkg/rpc/base"
	"gitee.com/851537/gpkg/rpc/server/plugin"
	"github.com/cloudwego/hertz/pkg/app/server/binding"

	//_ "gitee.com/851537/gpkg/vd"
	"github.com/cloudwego/hertz/pkg/common/hlog"
	"github.com/pkg/errors"
	"github.com/smallnest/rpcx/protocol"
	"github.com/smallnest/rpcx/server"
)

type Server struct {
	port     int
	s        *server.Server
	authFunc func(ctx context.Context, req *protocol.Message, tokenStr string) error

	//密钥
	secKey string

	//服务列表
	services []any

	//插件列表,see eg. server.PreCallPlugin
	plugins []any

	//是否启动debug日志
	debug bool

	//验证器
	ValidateConfig interface{}
}

func (this *Server) SetDebug(d bool) {
	this.debug = d
}

func (this *Server) Start() (err error) {
	this.s = server.NewServer()
	if this.authFunc == nil {
		return errors.New("Must init auth function")
	}

	//注册插件
	for _, v := range this.plugins {
		this.s.Plugins.Add(v)
	}

	//注册服务
	for _, v := range this.services {
		if err = this.s.Register(v, ""); err != nil {
			return
		}
	}

	this.s.AuthFunc = this.authFunc

	hlog.Debugf("rpc server port:%d", this.port)
	if err = this.s.Serve("tcp", fmt.Sprintf(":%d", this.port)); err != nil {
		hlog.Error("rpc service start err:", err.Error())
		return
	}
	return nil
}

func NewServer(opts ...gbase.Option[*Server]) (obj *Server) {
	obj = &Server{}
	for _, v := range opts {
		v(obj)
	}
	return
}

// 默认带上端口和签名校验方法的服务端，只要注入服务即可
func DefaultServer(opts ...gbase.Option[*Server]) (obj *Server) {
	obj = NewServer(opts...)
	if obj.port == 0 {
		obj.port = 1689
	}
	if obj.authFunc == nil {
		obj.authFunc = func(ctx context.Context, req *protocol.Message, tokenStr string) error {
			token := rpcbase.NewToken()
			if err := token.FromX(token, tokenStr); err != nil {
				return err
			} else if !token.CheckMd5(obj.secKey) {
				return errors.New("rpc token invalid")
			}
			return nil
		}
	}

	//默认注册调用前置和后置插件
	if len(obj.plugins) == 0 {
		obj.plugins = append(obj.plugins, &plugin.Log{})
	}

	//默认加上验证请求插件
	obj.plugins = append(obj.plugins, &plugin.Vd{})

	return obj
}

func WithDebug(d bool) gbase.Option[*Server] {
	return func(obj *Server) {
		obj.SetDebug(d)
	}
}

func WithPort(port int) gbase.Option[*Server] {
	return func(obj *Server) {
		obj.port = port
	}
}

func WithSecKey(secKey string) gbase.Option[*Server] {
	return func(obj *Server) {
		obj.secKey = secKey
	}
}

func WithAuthFunc(authFunc func(ctx context.Context, req *protocol.Message, tokenStr string) error) gbase.Option[*Server] {
	return func(obj *Server) {
		obj.authFunc = authFunc
	}
}

func WithLogPlugin() gbase.Option[*Server] {
	return func(obj *Server) {
		obj.plugins = append(obj.plugins, new(plugin.Log))
	}
}

func WithPlugins(plugins ...any) gbase.Option[*Server] {
	return func(obj *Server) {
		for _, v := range plugins {
			obj.plugins = append(obj.plugins, v)
		}
	}
}

func WithServices(services ...any) gbase.Option[*Server] {
	return func(obj *Server) {
		for _, v := range services {
			obj.services = append(obj.services, v)
		}
	}
}

func WithValidateConfig(vc *binding.ValidateConfig) gbase.Option[*Server] {
	return func(obj *Server) {

	}
}
